/**
 * 
 */
package com.gragra.wilsHandler;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.util.ArrayList;
/**
 * @author Christoph Teichmann
 * 24.09.2013
 */
public class WilsToPunctuationFreeWithEvaluateSentences
{
	/**
	 * 
	 */
	private final static int	WordPostion = 1;
	/**
	 * 
	 */
	private final static int CoarsePosition = 3;
	/**
	 * 
	 */
	private static final int FinePosition = 4;
	/**
	 * 
	 */
	private final static int UniversalPosition = 5;
	/**
	 * 
	 */
	private final static int HeadPosition = 7;
	/**
	 * first argument is output prefix, first file is assumed to be gold file
	 * @param args
	 * @throws IOException 
	 */
	public static void main(BufferedWriter gold,BufferedWriter allUniversal, BufferedWriter allCoarse, BufferedWriter allFine, BufferedReader[] files, int max) throws IOException
	{
		int goldEnd = 0;
		IntArrayList position = new IntArrayList();
		IntArrayList goldPosition = new IntArrayList();
		ArrayList<String> words = new ArrayList<String>();
		ArrayList<String> coarse = new ArrayList<String>();
		ArrayList<String> universal = new ArrayList<String>();
		ArrayList<String> fine = new ArrayList<String>();
		for(int i = 0; i < files.length; i++)
		{
			BufferedReader bufferedReader = files[i];
			String line;
			while((line = bufferedReader.readLine()) != null)
			{
				line = line.trim();
				if(line.equals(""))
				{
					goldEnd = writeOut(gold, allUniversal, allCoarse,allFine, max,
							goldEnd, position, goldPosition, words, coarse,
							universal,fine, i);
				}
				else
				{
					String[] parts = line.split("\\s+");
					words.add(parts[WordPostion ]);
					coarse.add(parts[CoarsePosition]);
					universal.add(parts[UniversalPosition]);
					fine.add(parts[FinePosition]);
					if(i == 0)
					{
						String s = parts[HeadPosition];
						s = s.equals("ROOT") ? "0" : s;
						goldPosition.add(Integer.parseInt(parts[HeadPosition]));
					}
				}
			}
			bufferedReader.close();
			goldEnd = writeOut(gold, allUniversal, allCoarse,allFine, max,
					goldEnd, position, goldPosition, words, coarse,
					universal,fine, i);
		}
		allCoarse.close();
		allUniversal.close();
		gold.close();
		System.out.println(goldEnd);
	}
	/**
	 * @param gold
	 * @param allUniversal
	 * @param allCoarse
	 * @param allFine 
	 * @param max
	 * @param goldEnd
	 * @param position
	 * @param goldPosition
	 * @param words
	 * @param coarse
	 * @param universal
	 * @param fine 
	 * @param i
	 * @return
	 * @throws IOException
	 */
	protected static int writeOut(BufferedWriter gold,
			BufferedWriter allUniversal, BufferedWriter allCoarse, BufferedWriter allFine, int max,
			int goldEnd, IntArrayList position, IntArrayList goldPosition,
			ArrayList<String> words, ArrayList<String> coarse,
			ArrayList<String> universal, ArrayList<String> fine, int i) throws IOException
	{
		if(test(max, words, universal))
		{
			if(goldEnd != 0)
			{
				if(i==0)
				{gold.newLine();}
				allCoarse.newLine();
				allUniversal.newLine();
				allFine.newLine();
			}
			handle(position,goldPosition,words,coarse,universal);
			if(i == 0)
			{
				++goldEnd;
				writeOutGold(words,position,goldPosition,gold);
			}
			writeOutLine(words,coarse, position, allCoarse);
			writeOutLine(words,universal, position, allUniversal);
			writeOutLine(words,fine, position, allFine);
		}
		words.clear();
		coarse.clear();
		universal.clear();
		position.clear();
		goldPosition.clear();
		fine.clear();
		return goldEnd;
	}
	/**
	 * @param max
	 * @param words
	 * @return
	 */
	protected static boolean test(int max, ArrayList<String> words, ArrayList<String> universal)
	{
		boolean seen = false;
		for(int i=0;i<universal.size();++i)
		{
			seen |= !universal.get(i).trim().equals(".");
		}
		return seen && !words.isEmpty() && (words.size() <= max || max <= 0);
	}
	/**
	 * 
	 * @param position
	 * @param goldPosition
	 * @param words
	 * @param coarse
	 * @param universal
	 */
	private static int handle(IntArrayList position,
			IntArrayList goldPosition, ArrayList<String> words,
			ArrayList<String> coarse, ArrayList<String> universal)
	{
		int pos = 1;
		position.clear();
		for(int i=0;i<words.size();++i)
		{
			if(universal.get(i).equals("."))
			{position.add(-1);}
			else
			{position.add(pos++);}
		}
		return pos-1;
	}
	/**
	 * 
	 * @param words
	 * @param coarse
	 * @param allCoarse
	 * @throws IOException 
	 */
	private static void writeOutLine(ArrayList<String> words,
			ArrayList<String> coarse,IntArrayList position, BufferedWriter allCoarse) throws IOException
	{
		boolean first = true;
		for(int i=0;i<coarse.size();++i)
		{
			if(position.get(i)==-1)
			{continue;}
			if(first)
			{first=false;}
			else
			{allCoarse.write(" ");}
			allCoarse.write(words.get(i));
			allCoarse.write("|");
			allCoarse.write(coarse.get(i));
		}
	}
	/**
	 * 
	 * @param words
	 * @param position
	 * @param goldPosition
	 * @param gold
	 * @throws IOException 
	 */
	private static void writeOutGold(ArrayList<String> words,
			IntArrayList position, IntArrayList goldPosition, BufferedWriter gold) throws IOException
	{
		boolean first = true;
		for(int i=0;i<words.size();++i)
		{
			if(position.get(i) != -1)
			{
				if(first)
				{first=false;}
				else
				{gold.write(" ");}
				gold.write(words.get(i));
			}
		}
		gold.newLine();
		first = true;
		for(int i = 0; i < position.size(); i++)
		{
			if(position.get(i) != -1)
			{
				if(first)
				{first=false;}
				else
				{gold.write(" ");}
				gold.write(Integer.toString(getHead(i,goldPosition,position)));
			}
		}
	}
	/**
	 * 
	 * @param i
	 * @param goldPosition
	 * @param position
	 * @return
	 */
	private static int getHead(int i, IntArrayList goldPosition,
			IntArrayList position)
	{
		int head = goldPosition.getInt(i);
		while(head != 0 && position.get(head-1) == -1)
		{head = goldPosition.getInt(head-1);}
		head = head == 0 ? 0 : position.getInt(head-1);
		return head;
	}
}